package com.xbongbong.sys.model;

import com.xbongbong.paas.pojo.vo.UserFormPermissionVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.wrap.IModel;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.sys.domain.entity.UserDepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.domain.entity.ext.UserEntityExt;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author kaka
 * @time 2018-8-28 14:15
 */
public interface UserModel extends IModel<UserEntity> {

    /**
     * 根据userId和corpid查询对应的用户
     * @param key 对应userId
     * @param corpid 公司id
     * @return 符合条件的用户实体
     */
    UserEntity getByKey(String key, String corpid);
    /**
     * 根据userId和corpid查询对应的用户
     * @param key 对应userId
     * @param corpid 公司id
     * @param del 删除标识
     * @return 符合条件的用户实体
     */
    UserEntity getByKey(String key, String corpid, Integer del);

    /**
     * 将userIds对应用户的roleId角色，批量去除
     * 1.员工角色只有1个不删除
     * 2.员工删除角色在原角色中没有不删除
     * 3.超级管理员角色不能删除，本条件在上层逻辑判断掉
     * 4.多用户，单角色
     * @param corpid 公司id
     * @param userIds 需要删除角色的用户id列表
     * @param roleId 需要被去除的角色
     * @return 返回1表示成功，0表示失败
     */
    Integer roleBathDel(String corpid, List<String> userIds, Integer roleId);

    /**
     * 为userIds对应用户增加roleId角色
     * 1.员工角色大于5个不添加
     * 2.员工添加角色与原角色相同不添加
     * 3.多用户，单角色
     * @param corpid 公司id
     * @param userIds 需要增加角色的用户id列表
     * @param roleId 需要被增加的角色
     * @return 返回1表示成功，0表示失败
     */
    Integer roleBathAdd(String corpid, List<String> userIds, Integer roleId);


    /**
     * 符合检索条件的用户数
     * @param param 检索条件
     * @return 符合条件的用户数量
     */
    @Override
    Integer getEntitysCount(Map<String, Object> param);

    /**
     * 根据条件检索用户列表
     * @param param 检索条件
     * @return 符合条件的用户列表
     */
    @Override
    List<UserEntity> findEntitys(Map<String, Object> param);

    /**
     * 根据userId列表检索
     * @param userIdsList
     * @param corpid
     * @return
     */
    List<UserEntity> findEntitysByUserIds(List<String> userIdsList, String corpid);


    /**
     * 根据筛选条件获取userId列表
     * @param param 筛选条件
     * @return 符合条件的userId列表
     */
    List<String> getUserIds(Map<String ,Object>  param);

    /**
     * 根据筛选条件获取userId列表
     * mapper内改方法已改为不连表--该方法访问的是表tb_user_department,与 getUserIds有所不同
     * 原方法名为 getUserIdsJoin TODO 梳理和重构
     * @param param 筛选条件
     * @return 符合条件的userId列表
     */
    List<String> getUserIdsJoin(Map<String ,Object>  param);

    /**
     * 通过数据权限，获取管理的员工userId列表, 可以选择排除或不排除自己（admin使用）
     * 5：全公司 4：自定义 3：本部门和下属部门，2本部门 1：本人
     * @param userEntity userEntity
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @param excludeOneSelf 是否排除自己，true 则排除自己，false不排除
     * @return 管理的员工userId列表
     * @author kaka
     */
    List<String> getSubIdsByDataPermission(UserEntity userEntity, int viewPermission, boolean excludeOneSelf);

    /**
     * 查询部门内的员工userId列表,不包含离职员工
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @return 部门内的员工userId列表
     */
    List<String> getDepUserIdList(String corpid, Collection<Long> depIdIn);

    /**
     * 查询部门内的员工userId列表，按部门分组
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @return {depId:[userId1,userId2]}
     */
    List<Map<String, Object>> getUserIdsJoinDeptGroup(String corpid, Collection<Long> depIdIn);

    /**
     * Description:
     * @param userEntity
     * @param saasMarkEnum
     * @param businessType
     * @param menuId
     * @return java.lang.Integer
     * @author 魏荣杰
     * @date 2020/6/3 12:22 上午
     */
    Integer getDataPermission(UserEntity userEntity, SaasMarkEnum saasMarkEnum, Integer businessType, Long menuId);

    /**
     * 查询部门内的员工userId列表 -不包含离职员工 (抄 方法getDepUserIdList)
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @return 部门内的员工userId列表
     */
    List<UserDepartmentEntity> getUserDepEntitiesByDepIds(String corpid, Collection<Long> depIdIn);
    /**
     * 查询部门内的员工userId列表
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @return 部门内的员工userId列表
     */
    List<String> getDepUserIdList(String corpid, Collection<Long> depIdIn, int viewPermission);
    /**
     * 查询部门内的员工userId列表,不包含不在可见范围的员工
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @return 部门内的员工userId列表
     */
    List<String> getDepUserIdList4Visible(String corpid, Collection<Long> depIdIn, int viewPermission);

    /**
     * （admin使用）
     * 获取某个员工的下属员工列表(userId列表),可选择排除或不排除自己
     * @param userEntity 需要获取下属员工userId列表的员工
     * @param ifAdminViewAll 管理员是否可以查看公司所有下属；
     *                       ifAdminViewAll=false管理员只能看下属；ifAdminViewAll=true 能看到所有
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工、且包含隐藏员工
     * @param excludeOneSelf 是否排除自己，true 则排除自己，false不排除
     * @return 返回下属员工 userId 列表
     * @author cp.zhang
     * @author kaka
     * @date 2017-3-3 下午5:03:51
     */
    List<String> getSubIdList(UserEntity userEntity, boolean ifAdminViewAll, int viewPermission, boolean excludeOneSelf) throws IllegalArgumentException;

    List<String> getSubIdListByDataPermission(Integer dataPermission, String userId, String corpid, int viewPermission, boolean excludeOneSelf);

    /**
     * 获取某个员工的下属员工列表(userId列表),可选择排除或不排除自己，不包含不在可见范围内的员工
     * @param dataPermission
     * @param userId
     * @param corpid
     * @param viewPermission
     * @param excludeOneSelf
     * @return
     */
    List<String> getSubIdListByDataPermission4Visible(Integer dataPermission, String userId, String corpid, int viewPermission, boolean excludeOneSelf);

    /**
     * 使用前需要使用 com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil#setValue
     * @param userVO
     * @param isOrganization
     * @return
     * @throws IllegalArgumentException
     */
    Integer getDataPermission(UserVO userVO, boolean isOrganization) throws IllegalArgumentException;

    /**
     * 使用前需要使用 com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil#setValue
     * @param userEntity
     * @param isOrganization
     * @return
     * @throws IllegalArgumentException
     */
    Integer getDataPermission(UserEntity userEntity, boolean isOrganization) throws IllegalArgumentException;

    /**
     * 使用前需要使用 com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil#setValue
     * @param dataPermissionDetail
     * @param corpid
     * @param rolesStr
     * @param isOrganization
     * @return
     * @throws IllegalArgumentException
     */
    Integer getDataPermission(Map<String, Integer> dataPermissionDetail, String corpid, String rolesStr, boolean isOrganization) throws IllegalArgumentException;
    /**
     * 获取员工 dataPermission
     * 使用前需要使用 com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil#setValue 设置一下数据权限信息
     * @param userEntity 需要获取dataPermission的员工
     * @return 5：全公司 4：自定义 3：本部门和下属部门，2本部门 1：本人
     * @throws IllegalArgumentException 参数异常
     */
    Integer getDataPermission(UserEntity userEntity) throws IllegalArgumentException;

    /**
     * //返回userIds
     * 获取部门极其下属部门的员工userId --- 递归，不包含隐藏部门、不包含离职员工
     * @param depIdIn 部门id列表
     * @param corpid 公司corpid
     * @return 部门极其下属部门的员工 userId
     */
    List<String> getUserIdsRecursionDep(List<Long> depIdIn,String corpid);

    /**
     * //返回userIds
     * 获取部门极其下属部门的员工id --- 递归，不包含隐藏部门
     * @param depIdIn   部门id列表
     * @param corpid 公司corpid
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @return
     * @author cp.zhang
     * @time 2017-3-3 下午7:13:49
     */
    List<String> getUserIdsRecursionDep(List<Long> depIdIn,String corpid, int viewPermission);

    /**
     * //返回userIds
     * 获取部门极其下属部门的员工id --- 递归
     * @param depIdIn 部门id列表
     * @param corpid 公司corpid
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @param showHidden 是否考虑隐藏部门（即del = 2的部门），true 显示，false 不显示
     * @return java.util.List<java.lang.String> 员工userIds
     * @author zcp
     * @date 2019/2/14 9:01
     * @since v1.0
     * @version v1.0
     */
    List<String> getUserIdsRecursionDep(List<Long> depIdIn,String corpid, int viewPermission, boolean showHidden);
    /**
     * Description: 根据角色获得用户id
     * @param corpid 公司id
     * @param roleIdList 角色list
     * @return java.util.List<java.lang.String>
     * @author 魏荣杰
     * @date 2019/2/14 15:23
     * @since v1.0
     */
    List<String> getUserIdsByRoles(String corpid, List<Integer> roleIdList);

    /**
     * Description: 根据useid批量获取user实体
     * @param corpid 公司id
     * @param userIdIn 用户ids
     * @return java.util.List<com.xbongbong.sys.domain.entity.UserEntity>
     * @author 吴峰
     * @date 2021/9/16 22:07
     * @since v1.0
     */
    List<UserEntity> getByUserIdIn(String corpid, Collection<String> userIdIn);
    /**
     * Description: 根据useid批量获取user实体
     * @param corpid 公司id
     * @param userIdIn 用户ids
     * @param ignoreDel
     * @return java.util.List<com.xbongbong.sys.domain.entity.UserEntity>
     * @author 魏荣杰
     * @date 2019/2/19 10:27
     * @since v1.0
     */
    List<UserEntity> getByUserIdIn(String corpid, Collection<String> userIdIn, boolean ignoreDel);

    /**
     * Description: 根据useid批量获取user实体
     * @param corpid 公司id
     * @param userIdIn 用户ids
     * @param del
     * @return java.util.List<com.xbongbong.sys.domain.entity.UserEntity>
     * @author 吴峰
     * @date 2022/2/23 14:09
     * @since v1.0
     */
    List<UserEntity> getByUserIdIn(String corpid, Collection<String> userIdIn, Integer del);
    /**
     * 判断是否Boss
     *
     * @param userEntity 用户实体
     * @author GuoJun.HU
     * @since V1.0
     * @return boolean
     * @date 2019/2/19 20:34
     */
    boolean isBoss(UserEntity userEntity);

    /**
     * 获取以用户id为key的用户名Map
     * @param corpid 公司id
     * @param userIds 用户id队列
     * @return Map<String, String> 以用户id为key的用户名Map
     *
     * @author 章华隽
     * 创建时间：2017/11/17 下午9:27
     * 修改时间：
     * @since 3.14
     */
    Map<String, String> getUserIdNameMap(String corpid, Collection<String> userIds);

    /**
     * 根据id查询name
     *
     * @param corpid
     * @param userList
     * @return
     */
    Map<String,String> getUserNameMap(String corpid, List<String> userList);

    /**
     * 根据id查询name
     *
     * @param corpid
     * @param userList
     * @param leaveMarks 离职标志，1:为需要
     * @return
     */
    Map<String,String> getUserNameMap(String corpid, List<String> userList,Integer leaveMarks);
    /**
     * 根据id查询用户
     *
     * @param corpid
     * @param userList
     * @param leaveMarks 离职标志，1:为需要
     * @return
     */
    Map<String, UserEntity> getUserEntityMap(String corpid, List<String> userList, Integer leaveMarks);
    /**
     * 获取该公司所有员工的name id键值对
     * @param corpid
     * @return
     */
    Map<String,String> getUserNameMapping(String corpid);

    /**
     * 该方法是对getUserBelongDeptIdList()方法的重构：增加了xbb内助理部门ids的获取
     * （1）获得用户所属部门id列表
     * （2）若managedDep为true：1.返回管理的部门ID[在该部门为管理员]，2.返回所有助理部门
     *
     * @param userEntity 登录员工
     * @param managedDep 若managedDep为true则返回管理的部门ID[在该部门为管理员]以及xbb内所有助理部门ids,若为false则返回所在部门的id列表
     * @return 部门ids
     * @since v3.21
     * @version v3.21
     * @author cp.zhang
     * 创建时间：2018-5-7 下午3:41:29
     * 修改时间：
     */
    List<Long> getUserManageDeptIdList(UserEntity userEntity, boolean managedDep);

    /**
     * pk榜获取的员工id列表
     * @param userEntity 员工
     * @param pkLeave 是否包含离职员工
     * @return
     * @throws
     *
     * @author hongxiao
     * @date: 2019-02-22 19:34
     * @since v1.0
     * @version v1.0
     */
    List<String> getPkUserIdIn(UserEntity userEntity, boolean pkLeave, Integer dataPermission);

    /**
     * pk榜获取的员工列表，要先通过方法getPkUserIdIn()得到userIdIn
     * @param userEntity 登录员工
     * @param userIdIn 员工ids
     * @param pkLeave 是否包含离职员工
     * @return java.util.List<com.xbongbong.sys.domain.entity.UserEntity>
     * @author zcp
     * @date 2019/3/12 17:18
     * @since v1.0
     * @version v1.0
     */
    List<UserEntity> getPkUserList(UserEntity userEntity, List<String> userIdIn, boolean pkLeave);

    /**
     * 根据条件检索用户列表 拼音首字母排序
     * @param param 检索条件
     * @return 符合条件的用户列表
     */
    List<UserEntityExt> findEntitysOrderByPinyin(Map<String, Object> param);

    /**
     * 批量获取用户
     * @param userIdList
     * @param corpid
     * @return
     */
    List<UserEntity> getByUserId(List<String> userIdList, String corpid);

    /**
     * 获取客户（不管是否离职）
     *
     * @param key
     * @param corpid
     * @return
     */
    UserEntity getByKeyIngoreDel(String key, String corpid);

    /**
     * 获得用户所属部门id列表,若managedDep为true则返回管理的部门ID[在该部门为管理员]
     * @param userEntity
     * @param managedDep 若managedDep为true则返回管理的部门ID[在该部门为管理员],若为false则返回所在部门的id列表
     * @return
     * kaka
     * 2017年4月8日 下午1:56:49
     * 修改时间： 2017-07-12 20:11 by chy
     */
    List<Long> getUserBelongDeptIdList(UserEntity userEntity, boolean managedDep);

    /**
     * 获得用户所属部门id列表,若managedDep为true则返回管理的部门ID[在该部门为管理员]
     * @param corpid
     * @param userId
     * @param managedDep 若managedDep为true则返回管理的部门ID[在该部门为管理员],若为false则返回所在部门的id列表
     * @return
     * kaka
     * 2017年4月8日 下午1:56:49
     * 修改时间： 2017-07-12 20:11 by chy
     */
    List<Long> getUserBelongDeptIdList(String corpid, String userId, boolean managedDep);

    /**
     * 获得用户所属部门名称列表
     * @param corpid
     * @param userIdIn
     * @return 用户ID--部门名称
     * kaka
     * 2020年11月6日 下午1:56:49
     * 修改时间： 2020-11-12 20:11 by youli.chen
     */
    Map<String, String> getUserBelongDeptNameMap(String corpid, List<String> userIdIn);

    /**
     * 规范userList，转换为各个部门对应的员工list
     * @param userList 员工list
     * @return java.util.Map<java.lang.Long,java.util.Set<java.lang.String>> 格式为：部门id---该部门员工id list
     * @author zcp
     * @date 2019/3/12 19:48
     * @since v1.0
     * @version v1.0
     */
    Map<Long, Set<String>> getDepIdUserIdsMap(List<UserEntity> userList);


    /**
     * 更新微应用可见状态,单个公司所有用户
     * isVisbile与del有一定的关联，del=1的记录不需处理，del=0表示是可见有效的用户，del=2表示是不可见没有使用的用户
     * @param corpid	公司ID
     * @param isVisible 1可见[授权]，0不可见[不授权]
     * @return
     * @author kaka
     * @time 2016年7月18日 下午3:52:16
     */
    Integer updateAllVisibleByCorpId(String corpid, Integer isVisible);

    /**
     * 更新微应用不可见状态 ,单个公司单个或多个用户
     * @param corpid 公司ID
     * @param isVisible 1可见[授权]，0不可见[不授权]
     * @param userIdNotIn 不可见的用户列表
     * isVisbile与del有一定的关联，del=1的记录不需处理，del=0表示是可见有效的用户，del=2表示是不可见没有使用的用户
     * @author kaka
     * @time 2016年7月18日 下午3:55:23
     */
    Integer updateVisibleByCorpIdAndUserIdNotIn(String corpid, Integer isVisible, List<String> userIdNotIn);

    /**
     * 删除指定公司更新时间小于某个时间点的员工数据，
     * 主要用途是在组织架构同步完成后将未更新到的员工表信息置为删除状态，
     * 代替原来的提前删除逻辑
     * @param corpid 公司ID
     * @param updateTime 更新时间
     * @return 数据库操作返回，1表示成功，0表示失败
     * @author kaka
     * @date 2018年1月9日
     */
    Integer clearUnauthUserByUpdateTime(String corpid, Integer updateTime);

    /**
     * 获取员工助理的部门id列表
     * @param corpid 公司id
     * @param userId 员工userId
     * @return userId员工助理的部门id列表
     */
    List<Long> getUserAssistDepIdList(String corpid, String userId);

    /**
     * 获取员工助理的员工userId列表
     * @param corpid 公司id
     * @param userId 员工userId
     * @return userId员工助理的员工userId列表
     */
    List<String> getUserAssistUserIdList(String corpid, String userId);

    /**
     * 删除某公司的用户
     * @param corpid 公司id
     * @return 影响的记录数
     */
    Integer deleteByCorpId(String corpid);

    /**
     * 通过系统默认的角色获取用户
     *
     * @param corpid        公司id
     * @param roleIdList    角色id
     * @author GuoJun.HU
     * @since V1.0
     * @return List
     * @date 2019/4/19 19:18
     */
    List<UserEntity> getUsersByRoleId(String corpid, List<Integer> roleIdList);

    /**
     * 根据用户ID集合获取用户名称
     *
     * @param corpId 公司ID
     * @param userIdIn 用户ID集合
     * @return users
     */
    List<UserEntity> getUserNamesByIdIn(String corpId, List<String> userIdIn);


    /**
     * 根据用户ID集合获取用户名称
     *
     * @param corpId 公司ID
     * @param userIdIn 用户ID集合
     * @return users
     */
    List<UserEntity> getUserNamesByIdIn(String corpId, Collection<String> userIdIn, Integer delIgnore);

    /**
     * 根据用户ID集合获取用户名称(包括离职人员)
     *
     * @param corpId 公司ID
     * @param userIdIn 用户ID集合
     * @return users
     */
    List<UserEntity> getUserNamesAllByIdIn(String corpId, List<String> userIdIn);


    /**
     * 查包含具有某个角色的员工记录，拿一条即可，只用于判断有无
     * @param corpid 公司id
     * @param roleId 角色id
     * @return 被赋予该角色的员工记录
     */
    List<UserEntity> getUserWithRole(String corpid, Integer roleId);

    /**
     * 过滤离职员工
     *
     * @param userIdList
     * @param corpid
     * @return
     */
    Set<String> filterOutDepartingUser(Set<String> userIdList, String corpid);

    /**
     * 获取主管的部门下属
     *
     * @param userEntity
     * @return
     */
    List<String> getManageUser(UserEntity userEntity);

    List<String> getDelUserIds(String corpid);

    /**
     * 获取公司管理员（1位）
     * @param corpid
     * @return
     */
    UserEntity getAdminUser(String corpid);
    /**
     * 获取用户VO信息，目前用于登录接口或者获取权限
     *
     * @param corpid              公司id
     * @param userId              用户id
     * @param userDetailFlag      UserVO中是否返回 Set<DepartmentVO> 和 Set<RoleVO>
     *                            默认不返回该数据，网关调用做权限判断时需要
     * @param paasPermissionsFlag 返回的用户中的 RoleVO 是否需要paasPermissions字段数据，
     *                            默认不返回该数据，网关调用做权限验证时需要
     * @lastUpdateDate 2021/10/20 16:07 将该方法从userService移到userModel
     * @return
     * @throws XbbException
     */
    UserVO getUserVO(String corpid, String userId, boolean userDetailFlag, boolean paasPermissionsFlag ) throws XbbException;
    /**
     * 更新用户VO中的部门和角色数据
     * @param userVO 用户VO
     * @param paasPermissionsFlag 是否需要返回paas数据
     * @lastUpdateDate 2021/10/20 16:07 将该方法从userService移到userModel
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws XbbException
     *
     */
    void assembleUserVO(UserVO userVO, boolean paasPermissionsFlag) throws IllegalAccessException, InstantiationException, XbbException;

    /**
     * Description: 返回有depset和roleset的uservo数据
     * @param corpid
	 * @param userId
     * @return com.xbongbong.paas.toolbox.wrap.UserVO
     * @author 魏荣杰
     * @date 2021/11/23 13:59
     */
    UserVO getUserVoRoleAndDepartment(String corpid, String userId);

    Integer updateBatch(List<UserEntity> userEntityList, String corpid);


    UserFormPermissionVO getUserFormPermission(String corpid, String userId, Long appId, Long menuId) throws XbbException;
}
